package com.banding.datastructure;

import java.util.function.Consumer;

/**
 * @param <E>
 * @author bd
 */
public class DynamicArray<E> {
    /**
     * 数组初始长度
     */
    private static final int INITIAL_CAPACITY = 16;

    /**
     * 数组
     */
    private Object[] array = {};

    /**
     * 当前元素个数
     */
    private int size = 0;

    /**
     * 构造器:初始化数组
     */
    public DynamicArray() {
        this.array = new Object[INITIAL_CAPACITY];
    }


    /**
     * 获取当前元素
     *
     * @return 个数
     */
    public int size() {
        return size;
    }

    /**
     * 判断动态数组是否为空
     */
    public boolean isEmpty() {
        return this.size == 0;
    }

    /**
     * 在指定位置插入新元素
     */
    public void add(int index, E element) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException(index);
        }

        if (size >= array.length) {
            grow();
        }

        for (int i = size - 1; i >= index; i--) {
            array[i + 1] = array[i];
        }
        array[index] = element;

        size++;
    }

    private void grow() {
        int currentLength = this.array.length;
        Object[] newArray = new Object[currentLength * 2];
        System.arraycopy(array, 0, newArray, 0, size);
        array = newArray;
    }

    /**
     * 在末尾插入新元素
     */
    public void add(E element) {
        add(size, element);
    }

    /**
     * 获取指定位置的元素
     */
    public E get(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException(index);
        }
        return (E) array[index];
    }

    /**
     * 删除指定位置的元素，并返回删除内容
     */
    public E remove(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException(index);
        }
        E result = (E) array[index];
        for (int i = index; i < size - 1; i++) {
            array[index] = array[index + 1];
        }
        size--;
        array[size] = null;
        return result;

    }

    /**
     * 修改指定位置的元素
     */
    public E set(int index, E element) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException(index);
        }
        E oldValue = (E) array[index];
        array[index] = element;
        return oldValue;
    }

    /**
     * 遍历数组元素
     */
    public void forEach(Consumer<E> consumer) {
        for (Object o : array) {
            consumer.accept((E) o);
        }
    }

    /**
     * 数组内容展示形式为[1,4,2,3,5]
     *
     * @return 数组元素列表
     */
    @Override
    public String toString() {
        if (isEmpty()) {
            return "[]";
        }
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0; i < size; i++) {
            sb.append((E) array[i]).append(",");
        }
        sb.replace(sb.length() - 1, sb.length(), "]");
        return sb.toString();
    }
}
